﻿using System;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Configuration;
using System.Collections.Generic;

namespace SBPweb.PROvibe.Business.Server.Library.Services
{

    public class CustomHost : ServiceHost
    {

        #region Private fields

        private Type tService;
        private Type tContract;
        private Dictionary<string, Uri> dictUrisByScheme = new Dictionary<string, Uri>();

        #endregion

        #region Constructor logic

        public CustomHost(Type serviceType, Type contractType, params Uri[] baseAddresses)
            : base(serviceType, baseAddresses)
        {
            tService = serviceType;
            tContract = contractType;
            if (baseAddresses != null)
            {
                FixUpAddresses();
                FixUpBaseAddresses();
            }
            ServiceMetadataBehavior metadataBehavior = new ServiceMetadataBehavior();
            metadataBehavior.HttpGetEnabled = true;
            Description.Behaviors.Add(metadataBehavior);
        }

        #endregion

        #region Property accessors

        public static int HttpPort
        {
            get
            {
                return Convert.ToInt32(ConfigurationSettings.AppSettings["serviceHostHttpPort"]);
            }
        }

        public static int TcpPort
        {
            get
            {
                return Convert.ToInt32(ConfigurationSettings.AppSettings["serviceHostTcpPort"]);
            }
        }

        #endregion

        #region Methods

        #region Overridden

        protected override void InitializeRuntime()
        {
            this.AddServiceEndpoint(
                tContract,
                new BasicHttpBinding(),
                dictUrisByScheme["http"]);

            //this.AddServiceEndpoint(
            //    tContract,
            //    new PollingDuplexHttpBinding(),
            //    dictUrisByScheme["http"]);

            Binding mexBinding = MetadataExchangeBindings.CreateMexHttpBinding();
            this.AddServiceEndpoint(
                typeof(IMetadataExchange),
                mexBinding,
                string.Format("{0}/mex", dictUrisByScheme["http"]));

            base.InitializeRuntime();
        }

        #endregion

        #region Helper functions

        private void FixUpAddresses()
        {
            foreach (Uri uri in BaseAddresses)
            {
                if (!dictUrisByScheme.ContainsKey(uri.Scheme))
                {
                    dictUrisByScheme.Add(uri.Scheme, uri);
                }
            }
            FixUpAddress("http", "http", HttpPort);
            FixUpAddress("http", "net.tcp", TcpPort);
        }

        private void FixUpBaseAddresses()
        {

            UriSchemeKeyedCollection uskc = new UriSchemeKeyedCollection();
            foreach (KeyValuePair<string, Uri> kvp in dictUrisByScheme)
            {
                if (!BaseAddresses.Contains(kvp.Value))
                {
                    uskc.Add(kvp.Value);
                }
            }
            InitializeDescription(uskc);
        }

        private void FixUpAddress(string oldScheme, string newScheme, int newPort)
        {
            if (!dictUrisByScheme.ContainsKey(newScheme) && dictUrisByScheme.ContainsKey(oldScheme))
            {
                Uri oldUri = dictUrisByScheme[oldScheme];
                Uri newUri = new Uri(string.Format("{0}://{1}:{2}{3}", newScheme, oldUri.Host, newPort, oldUri.PathAndQuery));
                dictUrisByScheme.Add(newScheme, newUri);
            }
        }

        #endregion

        #endregion

    }

}
